已經進入到最後一個領域了,Binary Exploitation,主要談的都是一些關於程式漏洞等等的,大部分都是C語言,一樣先來看看兩題熱身題吧~
這題是很基礎的Buffer overflow的題目,先來看看他提供的原始碼
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#define FLAGSIZE_MAX 64
char flag[FLAGSIZE_MAX];
void sigsegv_handler(int sig) {
fprintf(stderr, "%s\n", flag);
fflush(stderr);
exit(1);
}
void vuln(char *input){
char buf[16];
strcpy(buf, input);
}
int main(int argc, char **argv){
FILE *f = fopen("flag.txt","r");
if (f == NULL) {
printf("Flag File is Missing. Problem is Misconfigured, please contact an Admin if you are running this on the shell server.\n");
exit(0);
}
fgets(flag,FLAGSIZE_MAX,f);
signal(SIGSEGV, sigsegv_handler);
gid_t gid = getegid();
setresgid(gid, gid, gid);
if (argc > 1) {
vuln(argv[1]);
printf("Thanks! Received: %s", argv[1]);
}
else
printf("This program takes 1 argument.\n");
return 0;
}
這邊可以看到要觸發segmentation fault後 sigsegv_handler
會幫我們把Flag印出來,再看到vuln
這個函式,裡面做了一次strcpy但是他沒有做邊界檢查,所以我們可以在這邊讓他overflow,存取到不該存取的記憶體區段,造成segmentation fault,所以只要我們輸入超過16個字元以上就可能會觸發
那這邊就直接塞多一點給他看看
$ ./vuln 123456789012345678901234567890
picoCTF{ov3rfl0ws_ar3nt_that_bad_5d8a1fae}
Flag就出來囉
一樣看看他給的原始碼吧
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
int flag() {
char flag[48];
FILE *file;
file = fopen("flag.txt", "r");
if (file == NULL) {
printf("Flag File is Missing. Problem is Misconfigured, please contact an Admin if you are running this on the shell server.\n");
exit(0);
}
fgets(flag, sizeof(flag), file);
printf("%s", flag);
return 0;
}
int main(int argc, char **argv){
setvbuf(stdout, NULL, _IONBF, 0);
// Set the gid to the effective gid
gid_t gid = getegid();
setresgid(gid, gid, gid);
// real pw:
FILE *file;
char password[64];
char name[256];
char password_input[64];
memset(password, 0, sizeof(password));
memset(name, 0, sizeof(name));
memset(password_input, 0, sizeof(password_input));
printf("What is your name?\n");
fgets(name, sizeof(name), stdin);
char *end = strchr(name, '\n');
if (end != NULL) {
*end = '\x00';
}
strcat(name, ",\nPlease Enter the Password.");
file = fopen("password.txt", "r");
if (file == NULL) {
printf("Password File is Missing. Problem is Misconfigured, please contact an Admin if you are running this on the shell server.\n");
exit(0);
}
fgets(password, sizeof(password), file);
printf("Hello ");
puts(name);
fgets(password_input, sizeof(password_input), stdin);
password_input[sizeof(password_input)] = '\x00';
if (!strcmp(password_input, password)) {
flag();
}
else {
printf("Incorrect Password!\n");
}
return 0;
}
這邊可以看到再輸入帳號的時候
fgets(password_input, sizeof(password_input), stdin);
並沒有做任何邊界檢查,所以我們只要讓name和password在記憶體中是填滿的也就是他的資料都是連續的,那這樣下面做puts就會將整串印出來,所以我們輸入超過256個自原看看
這裡可以看到輸入了256個a之後,密碼就出現了
接著再重新輸入一次,就可以拿到Flag